package client_commands;

import utils.Constants;
import client.ClientApplication;

/**
 * Klasa koja predstavlja thread koji izvrsava komande. Svaka komanda se blokira (tj. ovaj
 * thread), dok se ne izvrsi komanda login. Na ovaj nacin je omoguceno da Reader thread i
 * dalje isporucuje poruke login komandi, dok je neka druga komanda blokirana (tj. ovaj
 * thread koji treba da izvrsi tu komandu). Ukoliko bi se u Reader thread-u pozivao
 * executeCommand, onda bi se Reader thread blokirao pri zahtevu semafora, i ne bi mogao
 * da isporucuje poruke login komandi.
 * 
 * @author UrosKrkic & Radivoje Popovic
 */
public class CommandExecutor extends Thread implements Constants {

	/**
	 * Referenca na objekat aplikacije.
	 */
	private ClientApplication theApp;
	
	/**
	 * Komanda koju treba izvrsiti.
	 */
	private Command command = null;
	
	
	/**
	 * Konstruktor.
	 * @param theApp - objekat aplikcije
	 * @param command - komanda koja se izvrsava
	 */
	public CommandExecutor(ClientApplication theApp, Command command) {
		this.theApp = theApp;
		this.command = command;
		
		this.start();
	}
	
	
	@Override
	public void run() {
		
		// ako je multicast poruka - prihvata se pre logovanja
		if (command.getCode() == SET_SERVER_INFO) {
			this.command.executeCommand(theApp);
		}
		else {
			try {
				/*
				 * Sprecava da klijent primi i izvrsi neku poruku (komandu) pre nego sto se zavrsi
				 * proces logovanja.
				 * Npr. server moze poslati klijentu neku offline poruku, a da se proces
				 * logovanja jos uvek nije zavrsio na klijentskoj strani.
				 * Semafor stopira ovaj thread, dok login thread ne oslobodi semafor za logovanje.
				 */
				ClientApplication.loginSemaphore.acquire();
			}
			catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			this.command.executeCommand(theApp);
			
			ClientApplication.loginSemaphore.release();
		}
		
		this.interrupt();
	}
	
	
}
